﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.Diagnostics;
using SpeakupBackend;
using System.Threading;
using GoogleCalendar;

namespace Frontend
{
    /// <summary>
    /// Interaction logic for UserControl1.xaml
    /// </summary>
    public partial class GCalendarControl : UserControl
    {
        public GCalendarControl()
        {
            InitializeComponent();
            InitReminderScaleComboBox();
            InitReminderMethodComboBox();
        }

        void InitReminderScaleComboBox()
        {
            ReminderScaleComboBox.Items.Clear();

            foreach (Reminder.ReminderScale scale in Enum.GetValues(typeof(Reminder.ReminderScale)))
            {
                ComboBoxItem item = new ComboBoxItem();            
                item.Content = scale.ToString();
                item.Tag = scale;
                ReminderScaleComboBox.Items.Add(item);
            }
        }

        void InitReminderMethodComboBox()
        {
            ReminderMethodComboBox.Items.Clear();

            foreach (Reminder.ReminderMethod scale in Enum.GetValues(typeof(Reminder.ReminderMethod)))
            {
                ComboBoxItem item = new ComboBoxItem();
                item.Content = scale.ToString();
                item.Tag = scale;
                ReminderMethodComboBox.Items.Add(item);
            }
        }

        void SelectReminderScale(Reminder.ReminderScale scale)
        {
            foreach (ComboBoxItem item in ReminderScaleComboBox.Items)
            {
                Reminder.ReminderScale currentScale = (Reminder.ReminderScale)item.Tag;
                if (currentScale == scale)
                {
                    item.IsSelected = true;
                    break;
                }
            }
        }

        Reminder.ReminderScale GetSelectedReminderScale()
        {
            ComboBoxItem item = (ComboBoxItem)ReminderScaleComboBox.SelectedItem;
            if (item != null)
            {
                return (Reminder.ReminderScale)item.Tag;
            }
            return Reminder.ReminderScale.Hours;
        }

        void SelectReminderMethod(Reminder.ReminderMethod method)
        {
            foreach (ComboBoxItem item in ReminderMethodComboBox.Items)
            {
                Reminder.ReminderMethod currentMethod = (Reminder.ReminderMethod)item.Tag;
                if (currentMethod == method)
                {
                    item.IsSelected = true;
                    break;
                }
            }
        }


        Reminder.ReminderMethod GetSelectedReminderMethod()
        {
            ComboBoxItem item = (ComboBoxItem)ReminderMethodComboBox.SelectedItem;
            if (item != null)
            {
                return (Reminder.ReminderMethod)item.Tag;
            }
            return Reminder.ReminderMethod.Email;
        }

        BackendContext m_backendCtx;
        public BackendContext BackendCtx
        {
            get
            {
                return m_backendCtx;
            }
            set
            {
                if(value != null)
                {
                    EnableSyncCheckBox.IsChecked = value.GoogleCalendarOptions.IsEnabled;
                    NameTextBox.Text = value.GoogleCalendarOptions.Name;
                    PasswordTextBox.Password = value.GoogleCalendarOptions.Password;

                    if (value.GoogleCalendarOptions.Reminder != null)
                    {
                        EnableNotificationCheckBox.IsChecked = true;
                        ReminderValueTextBox.Text = value.GoogleCalendarOptions.Reminder.Value.ToString();
                        SelectReminderScale(value.GoogleCalendarOptions.Reminder.Scale);
                        SelectReminderMethod(value.GoogleCalendarOptions.Reminder.Method);
                    }
                    else
                    {
                        EnableNotificationCheckBox.IsChecked = false;
                        ReminderValueTextBox.Text = "2";
                        SelectReminderScale(Reminder.ReminderScale.Hours);
                        SelectReminderMethod(Reminder.ReminderMethod.Email);
                    }
                    m_backendCtx = value;
                }
                else
                {
                    EnableSyncCheckBox.IsChecked = false;
                }
                UpdateUI();
            }
        }

        private bool m_synchronizing = false;

        private void SaveState()
        {
            if (m_backendCtx != null)
            {
                m_backendCtx.GoogleCalendarOptions.IsEnabled = EnableSyncCheckBox.IsChecked.Value;
                m_backendCtx.GoogleCalendarOptions.Name = NameTextBox.Text;
                m_backendCtx.GoogleCalendarOptions.Password = PasswordTextBox.Password;

                if (EnableNotificationCheckBox.IsChecked == true)
                {
                    Reminder reminder = new Reminder();
                    reminder.Scale = GetSelectedReminderScale();
                    reminder.Method = GetSelectedReminderMethod();

                    int value = reminder.Value;
                    Int32.TryParse(ReminderValueTextBox.Text, out value);
                    reminder.Value = value;

                    m_backendCtx.GoogleCalendarOptions.Reminder = reminder;
                }
                else
                {
                    m_backendCtx.GoogleCalendarOptions.Reminder = null;
                }
            }
        }

        private void UpdateUI()
        {
            if (!IsInitialized )
            {
                return;
            }

            if (m_synchronizing)
            {
                EnableSyncCheckBox.IsEnabled = false;
                NameTextBox.IsEnabled = false;
                PasswordTextBox.IsEnabled = false;
                SyncButton.IsEnabled = false;
                NotificationGroupBox.IsEnabled = false;
            }
            else
            {
                EnableSyncCheckBox.IsEnabled = true;
                bool enabled = EnableSyncCheckBox.IsChecked ?? false;
                NameTextBox.IsEnabled = enabled;
                PasswordTextBox.IsEnabled = enabled;
                NotificationGroupBox.IsEnabled = enabled;

                bool notificationEnabled = EnableNotificationCheckBox.IsChecked ?? false;
                ReminderValueTextBox.IsEnabled = notificationEnabled;
                ReminderMethodComboBox.IsEnabled = notificationEnabled;
                ReminderScaleComboBox.IsEnabled = notificationEnabled;

                if (enabled && NameTextBox.Text.Length > 0 && PasswordTextBox.Password.Length > 0)
                {
                    SyncButton.IsEnabled = true;
                }
                else
                {
                    SyncButton.IsEnabled = false;
                }
            }
        }
        

        private void Hyperlink_RequestNavigate(object sender, RequestNavigateEventArgs e)
        {
            Process.Start(new ProcessStartInfo(e.Uri.AbsoluteUri));
            e.Handled = true;
        }

        private void EnableSyncCheckBox_Click(object sender, RoutedEventArgs e)
        {
            UpdateUI();
            SaveState();

            PasswordTextBox.IsEnabled = EnableSyncCheckBox.IsChecked ?? false;
            NameTextBox.IsEnabled = EnableSyncCheckBox.IsChecked ?? false;
        }

        private void NameTextBox_TextChanged(object sender, TextChangedEventArgs e)
        {
            UpdateUI();
            SaveState();
        }

        private void PasswordTextBox_PasswordChanged(object sender, RoutedEventArgs e)
        {
            UpdateUI();
            SaveState();
        }

        private void SyncButton_Click(object sender, RoutedEventArgs e)
        {
            Sync();
            m_synchronizing = true;
            UpdateUI();
        }

        private void OnSyncStarted()
        {
            m_synchronizing = true;
            UpdateUI();

            ProgressBarBorder.Visibility = Visibility.Visible;
            MessageBorder.Visibility = Visibility.Collapsed;
        }

        private void OnSyncCompleted(int completed)
        {
            m_synchronizing = false;
            UpdateUI();

            MessageTextBox.Text = "Synchronized. Added "+completed+" classes to calendar. ";
            MessageTextBox.Foreground = Brushes.Green;

            MessageBorder.Visibility = Visibility.Visible;
            ProgressBarBorder.Visibility = Visibility.Collapsed;
        }

        private void OnSyncError(Exception ex)
        {
            m_synchronizing = false;
            UpdateUI();            

            String message = "";

            Exception curEx = ex;
            while (curEx != null)
            {
                message += curEx.Message;
                curEx = curEx.InnerException;

                if (curEx != null)
                {
                    message += "\n";
                }
            }

            MessageTextBox.Text = message;
            MessageTextBox.Foreground = Brushes.Red;

            MessageBorder.Visibility = Visibility.Visible;
            ProgressBarBorder.Visibility = Visibility.Collapsed;
        }

        private void Sync()
        {
            EventSynchronizer synchronizer = new EventSynchronizer(m_backendCtx.GoogleCalendarOptions.Name,
                                                                   m_backendCtx.GoogleCalendarOptions.Password);

            synchronizer.Reminder = m_backendCtx.GoogleCalendarOptions.Reminder;

            var startedProxy = new DelegateProxy<EventSynchronizer.OnSyncStarted>();
            synchronizer.SyncStarted += startedProxy.ProxyConsumer;
            startedProxy.ProxySource += OnSyncStarted;

            var completedProxy = new DelegateProxy<EventSynchronizer.OnSyncCompleted>();
            synchronizer.SyncCompleted += completedProxy.ProxyConsumer;
            completedProxy.ProxySource += OnSyncCompleted;

            var errorProxy = new DelegateProxy<EventSynchronizer.OnSyncError>();
            synchronizer.SyncError += errorProxy.ProxyConsumer;
            errorProxy.ProxySource += OnSyncError;

            Thread thread = new Thread(SyncThread);
            thread.Start(synchronizer);
        }

        private void SyncThread(Object arg)
        {
            EventSynchronizer synchronizer = (EventSynchronizer)arg;
            synchronizer.Synchronize(m_backendCtx);            
        }

        private void EnableNotificationCheckBox_Click(object sender, RoutedEventArgs e)
        {
            SaveState();
            UpdateUI();
        }

        private void ReminderValueTextBox_TextChanged(object sender, TextChangedEventArgs e)
        {
            SaveState();
            UpdateUI();
        }

        private void ReminderScaleComboBox_SelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            SaveState();
            UpdateUI();
        }

        private void ReminderMethodComboBox_SelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            SaveState();
            UpdateUI();
        }

        private void ReminderValueTextBox_PreviewTextInput(object sender, TextCompositionEventArgs e)
        {
            int result;
            String value = e.Text;

            e.Handled = true;
            if (Int32.TryParse(value, out result))
            {
                if (result >= 0)
                {
                    e.Handled = false;
                }
            }
        }
    }
}
